<?php 

class SerialnumberModel extends BaseModel {
	private $bitLength = 4;

	const STATUS_INIT = 0;
	const STATUS_USED = 1;
	const STATUS_DEL = -1;

	function __construct() {
		parent::__construct();
	}

	function tableName() {
		return 'serial_number';
	}

	function validateRule() {
		return $rule = array(
			'name' => array(
				'name' => '用户名',
				'rule' => '/[a-zA-Z]{6,16}/',
				'error' => '字母不区分大小写，6-16位',
			),
			'vcode' => array(
				'name' => '验证码',
				'rule' => '/[\da-zA-Z]{4}/',
				'error' => '非法的验证码',
			),
		);
	}

	/**
	 * 根据机器码和序列号计算注册码
	 * @param	machineCode
	 * snCode(string) 序列号， machineCode(string) 机器码
	 * @return
	 */
	public function getRegCode($snCode='', $machineCode='')
	{
		$regCode = "";
		$str1 = str_replace('-', '', $snCode);
		$str2 = str_replace('-', '', $machineCode);

		$charCodeSum = $this->_getCharCodeSum($str1) + $this->_getCharCodeSum($str2);

		for ($i = 0; $i < strlen($str1); $i++) 
		{
			$atStr1 = $this->_charCodeAt(substr($str1, $i, 1));
			$atStr2 = $this->_charCodeAt(substr($str2, $i, 1));

			$char = $this->_getCharByIndex($atStr1 + $atStr2 + $charCodeSum);
			$splitFlag = (($i + 1) % 4 == 0 && $i != (strlen($str1) - 1))?"-":"";

			$regCode .= $char . $splitFlag;
		}
		return $regCode;
	}

	function validateCode($code=null) {
		$rule = '/^([A-Z0-9]{4})-([A-Z0-9]{4})-([A-Z0-9]{4})$/';
		return preg_match($rule, $code);
	}

	function getYear($pyear) {
		if(empty($pyear)) {
			return date('Y');
		}

		$rule = '/^\d{4}$/';
		if(!preg_match($rule, $pyear, $match)) {
			return false;
		}

		return $pyear;
	}

	function getTotal($ptotal) {
		if(empty($ptotal)) {
			return 200;
		}

		if(!is_numeric($ptotal) || $ptotal < 1) {
			return false;
		}

		return $ptotal;
	}

	function validFirst($pfirst) {
		if(is_numeric($pfirst) || substr_count($pfirst, $this->_units())) {
			return false;
		}

		return strtoupper($pfirst);
	}

	function firstCode($firstWord) {
		$length = ($this->bitLength - strlen($firstWord));
		$nextWords = $this->_groupBits($length);

		return strtoupper($firstWord.$nextWords);
	}

	function getBatches() {
		return uniqid();
	}

	function fullSerial($first, $total = 3) {
		$code = '';

		do {
			$code = $this->_fullSerial($first, $total);
		} while($this->where('xuliehao = "'.$code.'"')->count());

		return $code;
	}

	function validateSerial($serial='') {
		$serial = $this->where('xuliehao = "'.$serial.'"')->getOne();

		// 不存在
		if(!$serial) {
			return 0;
		}

		// 已使用
		if($serial['status'] == '1') {
			return 1;
		}

		return true;
	}

	function validateMachine($machine='') {
		return $this->where('jiqima = "'.$machine.'"')->count();
	}

	function replaceSWord($code) {
		$config = $this->_sWord();
		return strtoupper(str_replace(array_keys($config), array_values($config), $code));
	}

	private function _getCharCodeSum($str) {
		$sum = 0;
		for ($i = 0; $i < strlen($str); $i++) 
		{
			$sum += (int)$this->_charCodeAt(substr($str, $i, 1));
		}
		return $sum;
	}

	private function _charCodeAt($str)//等同于js的_charCodeAt()  
	{  
	    $result = array();  
	    for($i = 0, $l = mb_strlen($str, 'utf-8');$i < $l;++$i)  
	    {  
	        $result[] = $this->_uniord(mb_substr($str, $i, 1, 'utf-8'));  
	    }  
	    return (int)join(",", $result);  
	}

	private function _uniord($str, $from_encoding = false)  
	{  
	    $from_encoding = $from_encoding ? $from_encoding : 'UTF-8';  
	    if (strlen($str) == 1)  
	        return ord($str);  
	    $str = mb_convert_encoding($str, 'UCS-4BE', $from_encoding);  
	    $tmp = unpack('N', $str);  
	    return $tmp[1];  
	}  

	/*
	 * 所有的随机单位
	 */
	private function _getCharByIndex($index) {
		$all_units = $this->_units();
		$stringLen = strlen($all_units);
		$index = $index%$stringLen;
		return substr($all_units, $index, 1);
	}

	private function _units() {
		return 'ABCDEFGHIJKMNPQRSTUVWXYZ23456789';
	}

	protected function _groupBits($length=4) {
		$bits = '';

		$untis = str_split($this->_units());
		shuffle($untis);

		foreach(array_rand($untis, $length) as $key => $val) {
			$bits .= $untis[$val];
		}

		return strtoupper($bits);
	}

	private function _fullSerial($first, $total = 3) {
		$fullSerial = array($first);
		for ($i=0; $i < $total; $i++) { 
			$fullSerial[] = $this->_groupBits();
		}

		return implode('-', $fullSerial);
	}

	private function _sWord() {
		return array(
			'Ａ' => 'A',
			'Ｂ' => 'B', 
			'Ｃ' => 'C',
			'Ｄ' => 'D',
			'Ｅ' => 'E',
			'Ｆ' => 'F',
			'Ｇ' => 'G',
			'Ｈ' => 'H',
			'Ｉ' => 'I',
			'Ｊ' => 'J',
			'Ｋ' => 'K',
			'Ｌ' => 'L',
			'Ｍ' => 'M',
			'Ｎ' => 'N',
			'Ｏ' => 'O',
			'Ｐ' => 'P',
			'Ｑ' => 'Q',
			'Ｒ' => 'R',
			'Ｓ' => 'S',
			'Ｔ' => 'T',
			'Ｕ' => 'U',
			'Ｖ' => 'V',
			'Ｗ' => 'W',
			'Ｘ' => 'X',
			'Ｙ' => 'Y',
			'Ｚ' => 'Z',
			'ａ' => 'a',
			'ｂ' => 'b',
			'ｃ' => 'c',
			'ｄ' => 'd',
			'ｅ' => 'e',
			'ｆ' => 'f',
			'ｇ' => 'g',
			'ｈ' => 'h',
			'ｉ' => 'i',
			'ｊ' => 'j',
			'ｋ' => 'k',
			'ｌ' => 'l',
			'ｎ' => 'n',
			'ｍ' => 'm',
			'ｏ' => 'o',
			'ｐ' => 'p',
			'ｑ' => 'q',
			'ｒ' => 'r',
			'ｓ' => 's',
			'ｔ' => 't',
			'ｕ' => 'u',
			'ｖ' => 'v',
			'ｗ' => 'w',
			'ｘ' => 'x',
			'ｙ' => 'y',
			'ｚ' => 'z',
			'１' => '1',
			'２' => '2',
			'３' => '3',
			'４' => '4',
			'５' => '5',
			'６' => '6',
			'７' => '7',
			'８' => '8',
			'９' => '9',
			'０' => '0',
		);
	}
}